/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.playground.core.service.impl;

import com.playground.core.entity.LoggedPlayer;
import com.playground.core.entity.PlayerStatus;
import com.playground.core.entity.Room;
import com.playground.core.entity.RoomStatus;
import com.playground.core.repository.RoomRepository;
import com.playground.core.service.RoomService;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Inject;

/**
 * This class is responsible for analizing the rooms and update their status
 * when it's necessary. It runs on a separated thread, and only one execution of
 * it is allowed, i.e. this class is a singleton.
 * 
 * @author Tiago Peres
 */
public final class RoomStatusUpdater implements Runnable {
    private static final RoomStatusUpdater INSTANCE = new RoomStatusUpdater();
    private boolean running;
    // the maximum time (milliseconds) the system waits for players confirmation (RoomStatus.waitingForPlaersConfirmation)
    public static final long TIMEOUT = 60000;
   
    private RoomRepository roomRepository;
    
    public RoomStatusUpdater(){
        running = false;
        System.out.println("RoomStatusUpdater has been created.");
    }
    
    public void start(){
        running = true;
        new Thread(INSTANCE).start();
    }
    
    @Override
    public void run() {
        while(true){
            Iterator<Room> rooms = roomRepository.findRoomByStatus(RoomStatus.waitingForPlayersConfirmation).iterator();
            Long now = (new Date()).getTime();
            while (rooms.hasNext()){
                Room room = rooms.next();
                
                // if the time for players confirmation has expired
                if (room.getWaitingForPlayersConfirmationSince().getTime() + TIMEOUT <= now){
                    room.setStatus(RoomStatus.refused);
                    // remove the users that didn't confirm the game and set their status to online
                    Iterator<LoggedPlayer> players = room.getPlayers().iterator();
                    while (players.hasNext()){
                        LoggedPlayer lp = players.next();
                        if (!lp.getStatus().equals(PlayerStatus.ready)){
                            lp.setStatus(PlayerStatus.online);
                            players.remove();
                        }
                    }
                    // update room status index
                    roomRepository.save(room);
                }
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
                Logger.getLogger(RoomStatusUpdater.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    }
    
    public static synchronized RoomStatusUpdater getInstance(){
        return INSTANCE;
    }

    public boolean isRunning() {
        return running;
    }

    public void setRoomRepository(RoomRepository roomRepository) {
        this.roomRepository = roomRepository;
    }
}
